{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "112653c3-7b8c-4eca-a2fb-058781e6533c",
   "metadata": {},
   "source": [
    "# Python 模块化编程详解\n",
    "\n",
    "## 课程目标\n",
    "\n",
    "- 理解 Python 中的模块化编程概念。\n",
    "- 掌握模块的创建、导入和使用。\n",
    "- 学习包的组织结构及其中的 `__init__.py` 文件的作用。\n",
    "- 理解命名空间及其在模块化中的重要性。\n",
    "- 通过示例和练习，熟练运用 Python 的模块化和包管理。\n",
    "\n",
    "---\n",
    "\n",
    "## 1. 模块化编程简介\n",
    "\n",
    "### 1.1 什么是模块化编程？\n",
    "\n",
    "模块化编程是一种将程序分解为独立、可重用模块的编程方法。每个模块通常包含相关的函数、类和变量，可以独立开发和维护。\n",
    "\n",
    "### 1.2 模块化编程的优势\n",
    "\n",
    "- **代码复用**：模块可以被多个程序复用，减少重复代码。\n",
    "- **易于维护**：模块化代码更易于理解和调试。\n",
    "- **命名空间管理**：模块可以避免命名冲突。\n",
    "- **组织结构**：模块和包帮助组织大型项目。\n",
    "\n",
    "---\n",
    "\n",
    "## 2. Python 中的模块\n",
    "\n",
    "### 2.1 模块的定义\n",
    "\n",
    "- **模块**：一个包含 Python 代码的文件（`.py` 后缀），可以包含函数、类和变量。\n",
    "- **作用**：将相关的功能组织在一起，方便导入和使用。\n",
    "\n",
    "### 2.2 模块的创建\n",
    "\n",
    "创建一个简单的模块文件 `mymodule.py`：\n",
    "\n",
    "```python\n",
    "# mymodule.py\n",
    "def greet(name):\n",
    "    return f\"你好, {name}!\"\n",
    "```\n",
    "\n",
    "### 2.3 模块的导入\n",
    "\n",
    "- **语法**：\n",
    "  - `import 模块名`：导入整个模块。\n",
    "  - `from 模块名 import 对象名`：导入模块中的特定对象。\n",
    "  - `import 模块名 as 别名`：为模块指定别名。\n",
    "- **示例代码**："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6c0894de-154f-4364-9d03-2a9c87a75e8b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好, Alice!\n",
      "你好, Bob!\n",
      "你好, Charlie!\n"
     ]
    }
   ],
   "source": [
    "# 导入整个模块\n",
    "import mymodule\n",
    "print(mymodule.greet(\"Alice\"))  # 输出: 你好, Alice!\n",
    "\n",
    "# 导入特定对象\n",
    "from mymodule import greet\n",
    "print(greet(\"Bob\"))  # 输出: 你好, Bob!\n",
    "\n",
    "# 使用别名\n",
    "import mymodule as mm\n",
    "print(mm.greet(\"Charlie\"))  # 输出: 你好, Charlie!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6ad218d-f0d9-45c2-b04c-c14be4000fe9",
   "metadata": {},
   "source": [
    "### 2.4 模块的搜索路径\n",
    "\n",
    "- **定义**：Python 解释器在导入模块时会搜索的目录列表。\n",
    "- **查看路径**：\n",
    "\n",
    "```python\n",
    "import sys\n",
    "print(sys.path)\n",
    "```\n",
    "\n",
    "- **说明**：模块必须位于搜索路径中的一个目录下才能被导入。\n",
    "\n",
    "#### 课堂练习\n",
    "\n",
    "1. 创建一个模块 `math_utils.py`，包含 `add(a, b)` 和 `multiply(a, b)` 两个函数。\n",
    "2. 在另一个文件中导入并使用这两个函数，输出 `add(3, 4)` 和 `multiply(5, 6)` 的结果。\n",
    "\n",
    "---\n",
    "\n",
    "## 3. Python 中的包\n",
    "\n",
    "### 3.1 包的定义\n",
    "\n",
    "- **包**：一个包含多个模块的目录，必须包含一个 `__init__.py` 文件。\n",
    "- **作用**：组织和管理多个相关的模块。\n",
    "\n",
    "### 3.2 包的结构\n",
    "\n",
    "示例包 `mypackage` 的目录结构：\n",
    "\n",
    "```\n",
    "mypackage/\n",
    "├── __init__.py\n",
    "├── module1.py\n",
    "└── module2.py\n",
    "```\n",
    "\n",
    "### 3.3 `__init__.py` 文件的作用\n",
    "\n",
    "- **定义**：一个特殊文件，标记目录为 Python 包。\n",
    "- **作用**：\n",
    "  1. 初始化包的命名空间。\n",
    "  2. 定义包级别的属性和方法。\n",
    "  3. 控制包的导入行为（例如指定导入的内容）。\n",
    "- **示例代码**：\n",
    "\n",
    "```python\n",
    "# mypackage/module1.py\n",
    "def func1():\n",
    "    print(\"这是 module1 的 func1\")\n",
    "\n",
    "# mypackage/module2.py\n",
    "def func2():\n",
    "    print(\"这是 module2 的 func2\")\n",
    "\n",
    "# mypackage/__init__.py\n",
    "from .module1 import func1\n",
    "from .module2 import func2\n",
    "\n",
    "# 主程序\n",
    "import mypackage\n",
    "mypackage.func1()  # 输出: 这是 module1 的 func1\n",
    "mypackage.func2()  # 输出: 这是 module2 的 func2\n",
    "```\n",
    "\n",
    "### 3.4 包的导入\n",
    "\n",
    "- **语法**：\n",
    "  - `import 包名.模块名`\n",
    "  - `from 包名 import 模块名`\n",
    "  - `from 包名.模块名 import 对象名`\n",
    "- **示例代码**："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "18535885-5dc6-40db-a722-162ad835bbf5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这是 module1 的 func1\n",
      "这是 module2 的 func2\n"
     ]
    }
   ],
   "source": [
    "# 主程序\n",
    "import mypackage\n",
    "mypackage.func1()  # 输出: 这是 module1 的 func1\n",
    "mypackage.func2()  # 输出: 这是 module2 的 func2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "347da01c-22b3-4e4e-bcfb-f60b955cc12d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这是 module1 的 func1\n",
      "这是 module2 的 func2\n"
     ]
    }
   ],
   "source": [
    "# 导入包中的模块\n",
    "import mypackage.module1\n",
    "mypackage.module1.func1()\n",
    "\n",
    "# 导入模块中的对象\n",
    "from mypackage.module2 import func2\n",
    "func2()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70760cdc-22ec-4aed-803b-cb0e76c17c0a",
   "metadata": {},
   "source": [
    "#### 课堂练习\n",
    "\n",
    "1. 创建一个包 `utils`，包含两个模块 `string_utils.py`（定义 `to_upper(s)` 函数）和 `list_utils.py`（定义 `reverse_list(lst)` 函数）。\n",
    "2. 在 `__init__.py` 中导入这两个函数。\n",
    "3. 在外部文件中导入包并测试：将字符串 `\"hello\"` 转换为大写，并反转列表 `[1, 2, 3]`。\n",
    "\n",
    "---\n",
    "\n",
    "## 4. 命名空间\n",
    "\n",
    "### 4.1 命名空间的定义\n",
    "\n",
    "- **命名空间**：一个将名称映射到对象的字典，用于避免命名冲突。\n",
    "- **作用**：确保不同模块中的同名对象不会相互干扰。\n",
    "\n",
    "### 4.2 模块与命名空间\n",
    "\n",
    "- **讲解**：\n",
    "  - 每个模块有自己的命名空间。\n",
    "  - 导入模块时，模块中的对象在其命名空间内，使用 `模块名.对象名` 访问。\n",
    "- **示例代码**："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "34834f63-f7b5-4bc1-8667-c8c051e9a917",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "module1\n",
      "module2\n"
     ]
    }
   ],
   "source": [
    "# # module1.py\n",
    "# var = \"module1\"\n",
    "\n",
    "# # module2.py\n",
    "# var = \"module2\"\n",
    "\n",
    "# main.py\n",
    "import module1\n",
    "import module2\n",
    "print(module1.var)  # 输出: module1\n",
    "print(module2.var)  # 输出: module2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6dbfa5af-adcf-4bc9-b4c3-ab6b81ce9283",
   "metadata": {},
   "source": [
    "### 4.3 全局与局部命名空间\n",
    "\n",
    "- **全局命名空间**：模块级别的命名空间。\n",
    "- **局部命名空间**：函数或方法内部的命名空间。\n",
    "- **示例代码**：\n",
    "\n",
    "```python\n",
    "# 全局变量\n",
    "global_var = \"global\"\n",
    "\n",
    "def func():\n",
    "    local_var = \"local\"  # 局部变量\n",
    "    print(global_var)  # 访问全局变量\n",
    "    print(local_var)\n",
    "\n",
    "func()\n",
    "# print(local_var)  # 报错: NameError\n",
    "```\n",
    "\n",
    "#### 课堂练习\n",
    "\n",
    "1. 创建两个模块 `a.py` 和 `b.py`，各定义一个同名函数 `func()`，分别打印 `\"A\"` 和 `\"B\"`。\n",
    "2. 在 `main.py` 中导入并调用这两个函数，观察命名空间如何避免冲突。\n",
    "\n",
    "---\n",
    "\n",
    "## 5. 综合练习\n",
    "\n",
    "### 练习 1：创建一个数学工具包\n",
    "\n",
    "- 创建一个包 `math_tools`，包含模块：\n",
    "  - `basic.py`：实现 `add(a, b)` 和 `subtract(a, b)`。\n",
    "  - `advanced.py`：实现 `multiply(a, b)` 和 `divide(a, b)`。\n",
    "- 在 `__init__.py` 中导入所有函数。\n",
    "- 在外部文件中导入包，计算并输出：`add(5, 3)`、`subtract(10, 4)`、`multiply(2, 6)` 和 `divide(15, 3)`。\n",
    "\n",
    "### 练习 2：命名空间实验\n",
    "\n",
    "- 创建两个模块 `module_a.py` 和 `module_b.py`，各定义一个变量 `data`（分别为 `\"A\"` 和 `\"B\"`）和一个函数 `process_data()`（打印各自的 `data`）。\n",
    "- 在 `main.py` 中导入并使用这两个模块中的对象，确保没有命名冲突。\n",
    "\n",
    "---\n",
    "\n",
    "## 6. 课程总结\n",
    "\n",
    "- **模块**：组织代码的基本单位，方便导入和复用。\n",
    "- **包**：包含多个模块的目录，需有 `__init__.py` 文件。\n",
    "- **__init__.py**：初始化包，控制导入行为。\n",
    "- **命名空间**：管理对象名称，避免冲突。\n",
    "- **模块化编程**：提高代码的可维护性和可扩展性。\n",
    "\n",
    "通过本课的学习和练习，您应该能够熟练使用 Python 的模块和包，理解 `__init__.py` 的作用以及命名空间的重要性，并能应用模块化编程思想组织代码。课后请完成练习并提出问题！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a760e4d6-0350-432d-9ebb-d8433146fb9a",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
